// -*- coding: utf-8 -*-

/**
 * @file hybrid_reduction.h
 * @brief Implementation of a consistency for hybrid problems.
 */

#ifndef _HYBRID_REDUCTION_H
#define _HYBRID_REDUCTION_H

#include "elisa/elisa_defs.h"
#include "elisa/elisa_reduction.h"
#include "elisa/elisa_observer.h"
#include "elisa/elisa_real_constraint.h"
#include "elisa/elisa_interval_test.h"
#include "elisa/elisa_interval_form.h"
#include "elisa/elisa_model.h"

#include "hybrid_model.h"

NAMESPACE_ELISA

/**
 * @ingroup Hybrid
 * @class HybridReduction
 * @brief Projection operator implementing a consistency for hybrid problems
 */
class HybridReduction : public Reduction
{
public:
	/**
 	 * Constructor
 	 * @param c the constraint to reduce
 	 * @param v the var that the domain must be reduced
 	 * @param cons the factory for IntrevalForm
 	 */
	HybridReduction(ContConstraint *c, IntervalFormFactory *cons)
	    : m_constr(c)
	{
		Reduction::post(c);

		/*
		// Listeners for propagation
		VarImplSet::iterator it;
		for (it = m_constr->beginVar(); it != m_constr->endVar(); ++it) {
			(*it)->dependsOn(this, DomainReduction);
		}
		*/
	}

	/**
 	 * Destructor
 	 */
	~HybridReduction ()
	{
	}

	/// Base class's virtual methods
	//@{
	double priority() const
	{
		return 50.0;
	}

	bool reductionAlgorithm();
	//@}

	string getReductionName() const
	{
		return "Hybrid";
	}

	void print(std::ostream & os, std::string indent, VecConstraints *v) const
	{
		os << "HybridReduction [";
		printConstraints(os, "", v);
		os << "]";
	}

private:
	ContConstraint *m_constr;	// continuous constraint

	/// Copy protection
	HybridReduction & operator=(const HybridReduction &);
	HybridReduction(const HybridReduction &);
};


/**
 * @ingroup Hybrid
 * @class HybridReductionFactory
 * @brief Generation of a reduction for hybrid problems
 * @see HybridReduction
 */
class HybridReductionFactory : public ReductionFactory
{
public:
	/**
 	 * Constructor
 	 * @param cons the factory for the intervalForm
 	 */
	HybridReductionFactory (IntervalFormFactory *iff)
		: m_iff(iff)
	{
	}

	/**
 	 * Destructor
 	 * @post the factory for intervalForm has been deleted
 	 */
	~HybridReductionFactory ()
	{
		delete m_iff;
	}

	/// @name Base class's virtual methods
	//@{
	void create(ModelRep *mo, SetReduction & s)
	{
		ConstraintHandler *ch = dynamic_cast<ConstraintHandler *>(mo);
		if (ch != 0) {
			ContConstraint *constraint = dynamic_cast<ContConstraint *>(ch->getConstraint());
			if (constraint != 0) {
				s.insert(new HybridReduction(constraint, m_iff));
			}
		}
	}
//@}

private:
	// Generation of interval form used by box-consistency
	IntervalFormFactory *m_iff;
};

END_NAMESPACE_ELISA

#endif //HYBRID_REDUCTION_H
